//
//  WNCycleView.swift
//  WalkNovel
//
//  Created by Kevin on 2023/9/1.
//

import UIKit

protocol WNCycleViewProtocol: AnyObject {
    func wncycleViewDidSelectedIndex(_ index: Int)
}

class WNCycleView: UIView {
    
    deinit {
        if timer != nil {
            timer?.invalidate()
            timer = nil
        }
    }
    
    lazy var placeholderImgView: UIImageView = {
        let image = UIImageView(image: UIImage(named: "placeholder_banner"))
        return image
    }()
    
    lazy var pageControl: ZPageControl = {
        let control = ZPageControl(frame: .init(x: 0, y: scaleWidth(155)-30, width: ScreenW-24, height: 30))
        control.dotSize = .init(width: 6, height: 6)
        control.pageIndicatorTintColor = .init(named: "gray_D0D0D0")!
        control.currentPageIndicatorTintColor = .init(named: "red_FE95B4")!
        control.alignment = .right
        return control
    }()
    
    lazy var collectionView: UICollectionView = {
        let layout = ZCycleLayout()
        layout.itemSize = .init(width: ScreenW-24, height: scaleWidth(155))
        layout.minimumInteritemSpacing = 10000
        layout.minimumLineSpacing = 0
        layout.scrollDirection = .horizontal
        let col = UICollectionView.init(frame: .zero, collectionViewLayout: layout)
        col.showsVerticalScrollIndicator = false
        col.showsHorizontalScrollIndicator = false
        col.backgroundColor = .clear
        col.isPagingEnabled = true
        col.scrollsToTop = false
        col.decelerationRate = UIScrollView.DecelerationRate(rawValue: 0.0)
        col.delegate = self
        col.dataSource = self
        col.register(WNCycleViewCell.self, forCellWithReuseIdentifier: WNCycleViewCell.identifier)
        return col
    }()
    
    weak var delegate: WNCycleViewProtocol?
    
    var timer: Timer?
    
    var timeInterval: Int = 2
    
    var itemsCount: Int = 0
        
    var realCount: Int = 0

    var bannerArr = [BookDetailModel]()
    
    override init(frame: CGRect) {
        super.init(frame: frame)
        addSubview(collectionView)
        addSubview(placeholderImgView)
        addSubview(pageControl)
        collectionView.snp.makeConstraints { make in
            make.edges.equalToSuperview()
        }
        placeholderImgView.snp.makeConstraints { make in
            make.edges.equalToSuperview()
        }
    }
    
    func setBookArr(_ bookArr: [BookDetailModel]?) {
        if let arr = bookArr, arr.count > 0 {
            placeholderImgView.isHidden = true
            bannerArr = arr
            realCount = arr.count
            itemsCount = arr.count*200
            collectionView.reloadData()
            collectionView.setContentOffset(.zero, animated: false)
            dealFirstPage()
            pageControl.numberOfPages = realCount
            pageControl.currentPage = currentIndex() % realCount
            startTimer()
        }
    }
    
    required init?(coder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }
    
    override func willMove(toWindow newWindow: UIWindow?) {
        super.willMove(toWindow: newWindow)
        if newWindow != nil {
            self.startTimer()
        }else {
            self.cancelTimer()
        }
    }
}

// MARK: - UICollectionViewDataSource/UICollectionViewDelegate
extension WNCycleView: UICollectionViewDelegate, UICollectionViewDataSource {
    
    func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
        return itemsCount
    }
    
    func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
        let cell = collectionView.dequeueReusableCell(withReuseIdentifier: WNCycleViewCell.identifier, for: indexPath) as! WNCycleViewCell
        cell.model = bannerArr[indexPath.item%realCount]
        return cell
    }
    
    func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
        let centerViewPoint = convert(collectionView.center, to: collectionView)
        if let centerIndex = collectionView.indexPathForItem(at: centerViewPoint) {
            if indexPath.item == centerIndex.item {
                let index = indexPath.item % realCount
                if delegate != nil {
                    delegate?.wncycleViewDidSelectedIndex(index)
                }
            }else {
                collectionView.scrollToItem(at: indexPath, at: .centeredHorizontally, animated: true)
            }
        }
    }
}

// MARK: - UIScrollViewDelegate
extension WNCycleView {
    func scrollViewWillBeginDragging(_ scrollView: UIScrollView) {
        cancelTimer()
        dealLastPage()
        dealFirstPage()
    }
    
    func scrollViewDidEndDragging(_ scrollView: UIScrollView, willDecelerate decelerate: Bool) {
        startTimer()
    }
    
    func scrollViewDidEndDecelerating(_ scrollView: UIScrollView) {
        scrollViewDidEndScrollingAnimation(scrollView)
    }
    
    func scrollViewDidEndScrollingAnimation(_ scrollView: UIScrollView) {
        let index = currentIndex() % realCount
        pageControl.currentPage = index
    }
    
    func scrollViewDidScroll(_ scrollView: UIScrollView) {
        pageControl.currentPage = currentIndex() % realCount
    }
}

// MARK: - deal the first page and last page
extension WNCycleView {
    func dealFirstPage() {
        if currentIndex() == 0 && itemsCount > 1 {
            collectionView.scrollToItem(at: IndexPath(item: itemsCount/2, section: 0), at: .centeredHorizontally, animated: false)
        }
    }
    func dealLastPage() {
        if currentIndex() == itemsCount-1 && itemsCount > 1 {
            collectionView.scrollToItem(at: IndexPath(item: itemsCount/2-1, section: 0), at: .centeredHorizontally, animated: false)
        }
    }
}
// MARK: - timer
extension WNCycleView {
    func startTimer() {
        if itemsCount <= 1 { return }
        cancelTimer()
        timer = Timer.init(timeInterval: Double(timeInterval), target: self, selector: #selector(timeRepeat), userInfo: nil, repeats: true)
        RunLoop.main.add(timer!, forMode: .common)
    }
    
    func cancelTimer() {
        if timer != nil {
            timer?.invalidate()
            timer = nil
        }
    }
    
    @objc func timeRepeat() {
        let current = currentIndex()
        var targetIndex = current+1
        if (current == itemsCount-1) {
            dealLastPage()
            targetIndex = itemsCount/2
        }
        collectionView.scrollToItem(at: IndexPath(item: targetIndex, section: 0), at: .centeredHorizontally, animated: true)
    }
    
    func currentIndex() -> Int {
        let itemWH = ScreenW-24
        let offsetXY = collectionView.contentOffset.x
        if itemWH == 0 { return 0 }
        let index = round(offsetXY / itemWH)
        return Int(index)
        
    }
}
